// 封装axios的请求，返回重新封装的数据格式
// 对错误统一处理
import axios, { Axios, AxiosRequestConfig } from 'axios'
import errorHandle from './errorHandle'
const CancelToken = axios.CancelToken

class HttpRequest {
    baseUrl: string
    pending: any

    constructor(baseUrl: string) {
        this.baseUrl = baseUrl
        this.pending = {}
    }
    // 获取axios的配置
    getInsideConfig() {
        const config = {
            baseURL: this.baseUrl,
            headers: {
                'Content-Type': 'application/json;charset=utf-8'
            },
            timeout: 10 * 1000
        }
        return config
    }

    removePending(key: string, isRequest: boolean = false) {
        if (this.pending[key] && isRequest) {
            this.pending[key]('取消重复请求')
        }
        delete this.pending[key]
    }
    // 设置拦截器
    interceptors(instance: Axios) {
        // 请求拦截器
        instance.interceptors.request.use((config) => {
            let key = config.url + '&' + config.method
            this.removePending(key, true)
            config.cancelToken = new CancelToken((c) => {
                // c是一个函数
                this.pending[key] = c
            })
            return config
        }, (err) => {
            errorHandle(err)
            return Promise.reject(err)
        })

        // 响应请求的拦截器
        instance.interceptors.response.use((res) => {
            let key = res.config.url + '&' + res.config.method
            this.removePending(key)
            if (res.status === 200) {
                return Promise.resolve(res.data)
            } else {
                return Promise.reject(res)
            }
        }, (err) => {
            errorHandle(err)
            return Promise.reject(err)
        })
    }
    // 创建实例
    request(options: any) {
        const instance = axios.create()
        const newOptions = Object.assign(this.getInsideConfig(), options)
        this.interceptors(instance)
        return instance(newOptions)
    }
    get(url: string, config: any = {}) {
        const options = Object.assign({
            method: 'get',
            url
        }, config)
        return this.request(options)
    }
    post(url: string, data: any, config: any = {}) {
        const options = Object.assign({
            method: 'post',
            url,
            data
        }, config)
        return this.request(options)
    }
    put(url: string, data: any, config: any = {}) {
        const options = Object.assign({
            method: 'put',
            url,
            data
        }, config)
        return this.request(options)
    }
    patch(url: string, data: any, config: any = {}) {
        const options = Object.assign({
            method: 'patch',
            url,
            data
        }, config)
        return this.request(options)
    }
    del(url: string, config: any = {}) {
        const options = Object.assign({
            method: 'post',
            url
        }, config)
        return this.request(options)
    }
}

export default HttpRequest